<template>
  <div class="table-box">
    <div class="card edit-form mb10">
      <el-form :inline="true" :model="generatorForm" ref="generatorFormRef" :rules="generatorFormRules" label-width="110px">
        <el-row>
          <el-col :span="6">
            <el-form-item label="数据库类型" prop="dataBaseType">
              <el-select v-model="generatorForm.dataBaseType" placeholder="请选择数据库类型" clearable>
                <el-option v-for="item in databaseTypeOptions" :key="item.value" :label="item.label" :value="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="数据库地址" prop="dataBaseUrl">
              <el-input v-model="generatorForm.dataBaseUrl" placeholder="127.0.0.1" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="数据库端口号" prop="dataBasePort">
              <el-input v-model="generatorForm.dataBasePort" placeholder="3306" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="数据库名称" prop="dataBaseName">
              <el-input v-model="generatorForm.dataBaseName" placeholder="generator" clearable/>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="6">
            <el-form-item label="数据库账号" prop="dataBaseUserName">
              <el-input v-model="generatorForm.dataBaseUserName" placeholder="请输入数据库账号" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="数据库密码" prop="dataBasePassword">
              <el-input v-model="generatorForm.dataBasePassword" type="password" placeholder="请输入数据库密码" show-password clearable/>
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="根包的名称" prop="basePackage">
              <el-input v-model="generatorForm.basePackage" placeholder="请输入根包的名称,com.baidu" clearable/>
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="作者名称" prop="author">
              <el-input v-model="generatorForm.author" placeholder="请输入作者名称" clearable/>
            </el-form-item>
          </el-col>

        </el-row>

        <el-row >
          <el-col :span="6">
            <el-form-item label="ORM框架" prop="ormType">
              <el-select v-model="generatorForm.ormType" placeholder="请选择ORM框架" clearable>
                <el-option v-for="item in ormTypeOptions" :key="item.value" :label="item.label" :value="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="18">
            <el-form-item label="数据库表名称" prop="dataBaseTableName" style="width: 91%">
<!--              <el-input v-model="generatorForm.dataBaseTableName" placeholder="请输入数据库表名称用英文逗号分割" clearable style="width: 100%"/>-->
              <el-select v-model="dataBaseTableName" multiple placeholder="Select" filterable style="width: 100%">
                <template #header>
                  <el-checkbox v-model="checkAll" :indeterminate="indeterminate" @change="handleCheckAll">全选</el-checkbox>
                </template>
                <el-option
                  v-for="item in options" :key="item.value" :label="item.label" :value="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="10">
            <el-form-item>
              <el-button type="primary" @click="connectionDatabase"><el-icon><Refresh/></el-icon>测试连接数据库</el-button>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="codeGeneration(generatorFormRef)"><el-icon><Upload/></el-icon>生成代码</el-button>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="downloadCode"><el-icon><Download/></el-icon>下载代码</el-button>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="resetting(generatorFormRef)">
                <el-icon>
                  <Refresh/>
                </el-icon>
                重置
              </el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <el-form-item label="文件地址" prop="fileUrl">
        <el-input v-model="fileUrl" placeholder="文件地址" disabled/>
      </el-form-item>

    </div>

    <div class="card edit-form">
      <el-button type="primary" @click="queryCodeGenerationLog"><el-icon><Search /></el-icon>查询</el-button>
      <el-table :data="tableData" border stripe style="width: 100%">
        <el-table-column prop="id" label="id" min-width="30"/>
        <el-table-column prop="dataBaseType" label="数据库类型" min-width="100"/>
        <el-table-column prop="dataBaseUrl" label="数据库地址" min-width="100"/>
        <el-table-column prop="dataBasePort" label="数据库端口号" min-width="100"/>
        <el-table-column prop="dataBaseName" label="数据库名称" width="150"/>
        <el-table-column prop="dataBaseUserName" label="数据库账号" min-width="100"/>
        <el-table-column prop="dataBasePassword" label="数据库密码" min-width="100"/>
        <el-table-column prop="dataBaseTableName" label="数据库表名称" min-width="180"/>
        <el-table-column prop="ormType" label="ORM框架" min-width="100"/>
        <el-table-column prop="basePackage" label="根包的名称" min-width="100"/>
        <el-table-column prop="author" label="作者" min-width="100"/>
        <el-table-column prop="createTime" label="创建时间" width="170"/>
      </el-table>
      <el-pagination
        v-model:current-page="queryPrams.pageNumber"
        v-model:page-size="queryPrams.pageSize"
        :page-sizes="[5, 10, 20, 50]"
        :small="small"
        :disabled="disabled"
        :background="background"
        layout="total,sizes, prev, pager, next,jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import {reactive, ref,onMounted,watch } from 'vue'
import {CodeGeneration} from "@/api/interface/code-generation";
import {ElMessage, FormInstance, FormRules} from "element-plus";
import type { CheckboxValueType } from 'element-plus'
import api from "@/api/modules/generator-api"
import {AxiosResponse} from "axios";

const generatorFormRef = ref<FormInstance>()
// 表单内容
const generatorForm = reactive<CodeGeneration.CodeGenerationParam>({
  // 数据库类型,oracle、mysql
  dataBaseType: '',
  // 数据库地址
  dataBaseUrl: '',
  // 数据库端口号
  dataBasePort: '',
  // 数据库名称
  dataBaseName: '',
  // 数据库账号
  dataBaseUserName: '',
  // 数据库密码
  dataBasePassword: '',
  // 数据库表名称
  dataBaseTableName: '',
  // ORM框架 mybatis-plus、 mybatis-flex
  ormType: '',
  // 根包的名称
  basePackage: '',
  // 作者名称
  author: ''
})

const dataBaseTableName = ref([])
const checkAll = ref(false)
const indeterminate = ref(false)
const options = ref<OptionItem[]>([])

// 表单校验
const generatorFormRules = reactive<FormRules<CodeGeneration.CodeGenerationParam>>({
  dataBaseType: [{required: true, message: '请选择数据库类型', trigger: 'change'}],
  dataBaseUrl: [{required: true, message: '请输入数据库地址', trigger: 'blur'}],
  dataBasePort: [{required: true, message: '请输入数据库端口号', trigger: 'blur'}],
  dataBaseName: [{required: true, message: '请输入数据库名称', trigger: 'blur'}],
  dataBaseUserName: [{required: true, message: '请输入数据库账号', trigger: 'blur'}],
  dataBasePassword: [{required: true, message: '请输入数据库密码', trigger: 'blur'}],
  dataBaseTableName: [{required: true, message: '请输入数据库表名称', trigger: 'change'}],
  ormType: [{required: true, message: '请选择ORM框架', trigger: 'change'}],
  basePackage: [{required: true, message: '请输入根包的名称', trigger: 'blur'}],
  author: [{required: true, message: '请输入作者名称', trigger: 'blur'}],
})
// 查询条件
const queryPrams = reactive<CodeGeneration.queryGenerationLog>({
  // 当前页
  pageNumber: 1,
  // 每页显示条数
  pageSize: 5,
  // 数据库类型,oracle、mysql
  dataBaseType: '',
  // 数据库地址
  dataBaseUrl: '',
  // 数据库名称
  dataBaseName: '',
  // 作者名称
  author: ''
})
// 总条数
const total = ref<number>(0)
const small = ref(true)
const background = ref(true)
const disabled = ref(false)
// 表单数据
const tableData = ref<any>([])
// 下载代码的参数
const fileUrl = ref("")
// 数据库类型
const databaseTypeOptions = [
  {value: 'oracle', label: 'oracle'},
  {value: 'mysql', label: 'mysql'}
]
// ORM框架类型
const ormTypeOptions = [
  {value: 'mybatis-plus', label: 'mybatis-plus'},
  {value: 'mybatis-flex', label: 'mybatis-flex'}
]

watch(dataBaseTableName, (val) => {
  if (val.length === 0) {
    checkAll.value = false
    indeterminate.value = false
  } else if (val.length === options.value.length) {
    checkAll.value = true
    indeterminate.value = false
  } else {
    indeterminate.value = true
  }
  generatorForm.dataBaseTableName = Object.values(dataBaseTableName.value).join(',')
})

const handleCheckAll = (val: CheckboxValueType) => {
  indeterminate.value = false
  if (val) {
    dataBaseTableName.value = options.value.map((_:[]) => _.value)
  } else {
    dataBaseTableName.value = []
  }
  generatorForm.dataBaseTableName = Object.values(dataBaseTableName.value).join(',')
}

// 重置
const resetting = (generatorForm: FormInstance | undefined) => {
  if (!generatorForm) return;
  dataBaseTableName.value = []
  generatorForm.resetFields();

};
// 测试连接数据库
const connectionDatabase = async () => {
  if (generatorForm.dataBaseType == "") {
    ElMessage.error('数据库类型不能为空!')
    return;
  } else if (generatorForm.dataBaseUrl == "") {
    ElMessage.error('数据库地址不能为空!')
    return;
  } else if (generatorForm.dataBasePort == "") {
    ElMessage.error('数据库端口号不能为空!')
    return;
  }else if (generatorForm.dataBaseName == "") {
    ElMessage.error('数据库名称不能为空!')
    return;
  }else if (generatorForm.dataBaseUserName == "") {
    ElMessage.error('数据库账号不能为空!')
    return;
  } else if (generatorForm.dataBasePassword == "") {
    ElMessage.error('数据库密码不能为空!')
    return;
  }
  const {msg} = await api.databaseConnection(generatorForm);
  ElMessage.success(msg)
  const {data} = await api.getTableNameList(generatorForm);
  options.value = data.map((item:string) =>({
    value:item,
    label:item
  }));
}
// 生成代码
const codeGeneration =  (formEl: FormInstance | undefined) => {
  if (!formEl) return
   formEl.validate(async (valid, fields) => {
    if (valid) {
      const {msg, data} = await api.codeGeneration(generatorForm);
      fileUrl.value = data
      ElMessage.success(msg)
    } else {
      console.log('error submit!', fields)
    }
  })
}
// 下载代码
const downloadCode = async () => {
  const res:AxiosResponse = await api.downloadCode({fileUrl:fileUrl.value})
  // 处理文件流
  const blob = new Blob([res.data]);
  // 获取 获取响应头 heads 中的 filename 文件名
  const temp = res.headers["content-disposition"].split(";")[1].split("filename=")[1];
  var fileName = decodeURIComponent(temp)
  // 兼容 edge 不支持 createObjectURL 方法
  if ("msSaveOrOpenBlob" in navigator) return window.navigator.msSaveOrOpenBlob(blob, '代码.zip');
  const blobUrl = window.URL.createObjectURL(blob);
  const exportFile = document.createElement("a");
  exportFile.style.display = "none";
  // exportFile.download = `${'代码'}${'.zip'}`;
  exportFile.href = blobUrl;
  exportFile.setAttribute('download', fileName)
  document.body.appendChild(exportFile);
  exportFile.click();
  // 去除下载对 url 的影响
  document.body.removeChild(exportFile);
  window.URL.revokeObjectURL(blobUrl);
}
// 初始化查询
onMounted(() => {
  queryCodeGenerationLog()
})

// 分页查询代码生成记录
const queryCodeGenerationLog = async () =>{
  const {data} = await api.queryGenerationLog(queryPrams);
  tableData.value = data.records
  total.value = data.totalRow
  // ElMessage.success(msg)
}

// 每页显示条数
const handleSizeChange = async (val: number) => {
  queryPrams.pageSize = val
  await queryCodeGenerationLog()
}
// 当前页
const handleCurrentChange = async (val: number) => {
  queryPrams.pageNumber = val
  await queryCodeGenerationLog()
}
</script>

<style lang="less" scoped>

</style>
